package com.jp.fm.servlet;

import static org.quartz.DateBuilder.futureDate;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import static org.quartz.TriggerBuilder.newTrigger;
import static org.quartz.TriggerKey.triggerKey;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.quartz.DateBuilder.IntervalUnit;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;

import com.jp.fm.HomeFinanceRunner;
import com.jp.fm.TestHelper;
import com.jp.fm.dao.AccountDao;
import com.jp.fm.dao.CategoryDao;
import com.jp.fm.data.Account;
import com.jp.fm.data.AccountType;
import com.jp.fm.data.Institution;
import com.jp.fm.scheduler.ScheduledAccountRefreshJob;

public class HFMServletContext implements ServletContextListener {

	@Override
	public final void contextDestroyed(final ServletContextEvent arg0) {

		// Grab the Scheduler instance from the Factory
		try {
			Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
			scheduler.shutdown(true);
		} catch (SchedulerException e1) {
			e1.printStackTrace();
		}

		// Clear out ehcache stuff
		HomeFinanceRunner.getCacheManager().shutdown();

		// shutdown DB
		Connection c = null;
		PreparedStatement p = null;
		try {
			c = HomeFinanceRunner.getConnection();
			p = c.prepareStatement("SHUTDOWN");
			p.execute();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			HomeFinanceRunner.closeConnection(c, p, null);
		}

		// unregister JDBC driver
		// This manually deregisters JDBC driver, which prevents Tomcat 7
		// from complaining about memory leaks
		Enumeration<Driver> drivers = DriverManager.getDrivers();
		while (drivers.hasMoreElements()) {
			Driver driver = drivers.nextElement();
			try {
				DriverManager.deregisterDriver(driver);
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public final void contextInitialized(final ServletContextEvent arg0) {

		System.setProperty("net.sf.ehcache.pool.sizeof.AgentSizeOf.bypass",
				"true");

		// Build up initial caches
		AccountType.findAll();
		Institution.findAll();
		List<Account> accounts = new AccountDao().findAll();
		new CategoryDao().findAll();

		// Only start the scheduler if it is enabled in the properties file
		boolean schedulerEnabled = false;
		InputStream inStream = TestHelper.class
				.getResourceAsStream("/hfm.properties");
		Properties props = new Properties();
		try {
			props.load(inStream);
			schedulerEnabled = Boolean.valueOf(props
					.getProperty("run_scheduler"));
		} catch (IOException e1) {
			e1.printStackTrace();
		}

		if (schedulerEnabled) {
			// Setup schedule account refreshes
			try {
				// Grab the Scheduler instance from the Factory
				Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

				// and start it off
				scheduler.start();

				for (Account account : accounts) {
					JobDetail job = newJob(ScheduledAccountRefreshJob.class)
							.withIdentity(account.getName() + "Job").build();
					job.getJobDataMap().put("AccountName", account.getName());

					Trigger trigger = newTrigger()
							.withIdentity(
									triggerKey(account.getName() + "Trigger",
											"myTriggerGroup"))
							.withSchedule(
									simpleSchedule()
											.withIntervalInMinutes(
													account.getRefreshInterval())
											.withMisfireHandlingInstructionNowWithRemainingCount()
											.repeatForever())
							.startAt(futureDate(1, IntervalUnit.MINUTE))
							.build();

					scheduler.scheduleJob(job, trigger);
				}
			} catch (SchedulerException e) {
				e.printStackTrace();
			}
		} else {
			System.out.println("Scheduler not enabled.");
		}
	}
}
